package ua.at.javac.client;

import java.util.List;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Image;

/**
 * Этот класс компилируется в javascript
 * вызывается из Wanalizer.html на стороне клиента
 * 
 * @author Michael.Michaelovich, Cherry
 * @version 103
 * @since 2012
 */
public class Wanalyzer implements EntryPoint {
	
	private final GreetingServiceAsync servletInterface = 
			GWT.create(GreetingService.class);
	Label labelLoading = new Label ("Загрузка...");
	Image indicatorLoad = new Image("img/loader.gif");
	
	// список городов подгружаемый из БД
	ListBox cityBox = new ListBox();
	ListBox cityBoxExtended = new ListBox();
	
	/**
	 * точка входа
	 */
	public void onModuleLoad() {
		// таблица для прогноза погоды на 5 дней по выбранному городу
		final Grid gridWeather = new Grid(6, 5);
		gridWeather.setBorderWidth(1);
		gridWeather.setVisible(false);
		RootPanel.get("center").add(gridWeather);
		
		// таблица для прогноза сравнительная по сайтам по выбранной дате
		final Grid gridWeatherExtended = new Grid(12, 7);
		gridWeatherExtended.setBorderWidth(1);
		gridWeatherExtended.setVisible(false);
		RootPanel.get("center").add(gridWeatherExtended);
		
		cityBox.setSize("170px", "200px"); 
		cityBox.setVisibleItemCount(10);
		RootPanel.get("listBox").add(cityBox);
		
		cityBoxExtended.setVisible(false);
		cityBoxExtended.setSize("170px", "200px"); 
		cityBoxExtended.setVisibleItemCount(10);
		RootPanel.get("listBoxExtended").add(cityBoxExtended);
		
		
		/**
		 * Получение списка городов от сервера в панель cityBox
		 */
		 servletInterface.getListCity(new AsyncCallback<List<String>>() {
				@Override
				public void onFailure(Throwable caught) {
					cityBox.addItem("Ошибка загрузки БД");
				}
				@Override
				public void onSuccess(List<String> result) {
					for (int i = 0; i < result.size(); i++){
						cityBox.addItem(result.get(i));
					}			
				}
		   });
 		
		/**
		 * Получение списков дат от сервера
		 */
		servletInterface.getListDate(new AsyncCallback<List<String>>() {
		@Override
			public void onFailure(Throwable caught) {
				cityBoxExtended.addItem("Ошибка загрузки БД");
			}
			@Override
			public void onSuccess(List<String> result) {
				for (int i = 0; i < result.size(); i++){
					cityBoxExtended.addItem(result.get(i));
				}			
			}
		});
		
		/**
		 * Соединение с сервером через сервлет и ожидание данных из БД
		 * @param cityQuery - город
		 */
		class ConnectorWeatherBase {
			/**
			 * Соединение с сервером через сервлет и ожидание данных из БД
			 * @param cityQuery - город
			 */
			public void getWeather(String cityQuery){
				// индикация ожидания загрузки
				indicatorLoading(true);
				servletInterface.getWeather(cityQuery,
					new AsyncCallback<List<String[]>>(){
						
						@Override
						public void onFailure(Throwable caught) {
							gridWeather.setHTML(0, 0, 
									"Ошибка связи с сервером");
						}
						
						@Override
						public void onSuccess(List<String[]> result) {
							// вывод на клиент прогноза за 5 дней
							setHtmlGrid(gridWeather, result);
							indicatorLoading(false);
							// индикация ожидания загрузки
							gridWeather.setVisible(true);
						}
					}
				);
			}
			/**
			* Получение через сервлет из БД погоды по городу 
			* за дату по всем серверам
			* @param cityQuery - город
			* @param dateQuery - дата погоды
			*/
			public void getExtendedWeather(
					String cityQuery,
					String dateQuery){
				// индикация ожидания загрузки
				indicatorLoading(true);
				servletInterface.getExtendedWeather(
						cityQuery,
						dateQuery,
						new AsyncCallback<List<String[]>>(){
							
							@Override
							public void onFailure(Throwable caught) {
								gridWeatherExtended.setHTML(0, 0,
										"Ошибка связи с сервером");
							}
							
							@Override
							public void onSuccess(
									List<String[]> result) {
								// вывод на клиент
								// таблицы прогноза за 5 дней
								setHtmlGridSite(
									gridWeatherExtended,
									result);
								indicatorLoading(false);
								// индикация ожидания загрузки
								gridWeatherExtended.setVisible(true);
							}
						}
				); 
			}
		}
		
		/**
		 * Класс выводит таблицу погоды по клику в списке	
		 */
		class BoxChangeHandler implements ChangeHandler{
			@Override
			public void onChange(ChangeEvent event) {
				int index = cityBox.getSelectedIndex();
				String city = cityBox.getItemText(index);
				// отображаем панель с датами
				cityBoxExtended.setVisible(true);
					RootPanel.get("centerHead").clear();
					RootPanel.get("centerHead").add(
							new HTML("<h1>" + city + 
									" прогноз на 5 дней</h1>"));
					gridWeather.setVisible(false);
					gridWeatherExtended.setVisible(false);
					new ConnectorWeatherBase().getWeather(city);
			}
		}
		BoxChangeHandler cityBoxHandler = new BoxChangeHandler();
		cityBox.addChangeHandler(cityBoxHandler);
		
		/**
		 * Класс выводит таблицу расширенной погоды по клику в списке дат
		 */
		class BoxExtendedChangeHandler implements ChangeHandler{
			@Override
			public void onChange(ChangeEvent event) {
				String city = cityBox.getItemText(
						cityBox.getSelectedIndex());
				String uptodate = cityBoxExtended.getItemText(
						cityBoxExtended.getSelectedIndex());
					RootPanel.get("centerHead").clear();
					RootPanel.get("centerHead").add(
							new HTML("<h1>" + city +
									" по источникам данных</h1>"));
					gridWeather.setVisible(false);
					gridWeatherExtended.setVisible(false);
					new ConnectorWeatherBase().getExtendedWeather(
							city, uptodate);
			}
		}
		BoxExtendedChangeHandler cityBoxExtendedHandler = 
				new BoxExtendedChangeHandler();
		cityBoxExtended.addChangeHandler(cityBoxExtendedHandler);
	}
	
	/**
	 * Отображение и скрытие индикатора загрузки (песочные часы)  
	 * @param show - отображение или скрытие
	 */
	protected void indicatorLoading(boolean show) {
		if (show){
			//indicatorLoad.setSize("220px", "19px");
			RootPanel.get("center").add(labelLoading);
			RootPanel.get("center").add(indicatorLoad);
			labelLoading.setVisible(true);
			indicatorLoad.setVisible(true);
		} else {
			labelLoading.setVisible(false);
			indicatorLoad.setVisible(false);
		}
	}
	
	/**
	 * Создает таблицу на странице HTML с прогнозом погоды из коллекции данных 
	 * @param grid - таблица
	 * @param result - коллекция данных содержит 20 строк с 0 по 19
	 * данные в виде	день1 от 0 до 3
	 *				  день2 от 4 до 7
	 *				  день3 от 8 до 11
	 *				  день4 от 12 до 15
	 *				  день5 от 16 до 19
	 */
	private void setHtmlGrid(final Grid grid, List<String[]> result) {
		// очистка таблицы в случае выдачи пустой коллекции из БД
		grid.clear(true);
		// заполнение заголовков столбцов
		grid.setHTML(0, 0, "дата");
		grid.setHTML(0, 1, "ночь");
		grid.setHTML(0, 2, "утро");
		grid.setHTML(0, 3, "день");
		grid.setHTML(0, 4, "вечер");
		for (int day=1; day<=5; day++){	 // перебор дней
			// первая строка в коллекции данных result
			// день * четыре периода дня (утро,день,вечер,ночь) 
			// то 4 (начать с первого)
			int firstResultCell = day*4-4;
			try {
				//если база вернула не пустую коллекцию
				if (result.size()>0){
					// заполняем столбец датой
					grid.setHTML (	day, 
									0, 
									result.get(firstResultCell)[1]);
					for (int cell = 1; cell<=4; cell++){
						int row = firstResultCell + cell-1;
						grid.setHTML (	day, 
										cell,
										cellText(result, row));
					}
				} else grid.setHTML(day, 0, "нет данных");
			} catch (Exception e) {
			}
		}
	}

	/**
	 * Создает таблицу на странице HTML
	 * с прогнозом погоды из коллекции данных 
	 * @param grid - таблица
	 * @param result - коллекция данных 
	 * содержит 12(20) строк с 0 по (11)19
	 * данные в виде	день1 от 0 до 3
	 */
	private void setHtmlGridSite (	final Grid grid, 
									List<String[]> result) {
		// очистка таблицы в случае выдачи пустой коллекции из БД
		grid.clear(true);
		
		// заполнение заголовков столбцов
		grid.setHTML(0, 0, "период");
		grid.setHTML(0, 1, "источник");
		grid.setHTML(0, 2, "облачность");
		grid.setHTML(0, 3, "температура");
		grid.setHTML(0, 4, "осадки");
		grid.setHTML(0, 5, "влажность");
		grid.setHTML(0, 6, "давление");
		
		// перебор периодов(утро,день,вечер,ночь)
		for (int p=1; p<=result.size(); p++){
			// день * четыре периода дня (утро,день,вечер,ночь) 
			// то - 4 (начать с первого)
			try {
				//если база вернула не пустую коллекцию
				if (result.size()>0){
					// период
					grid.setHTML(p, 0, result.get(p)[3]);
					// источник
					grid.setHTML(p, 1, result.get(p)[4]);
					// облачность
					grid.setHTML(p, 2, "<p align='center'>" + 
									"<p align='center'><img src=" +
									"img/cloudiness50.gif></br>"+
									result.get(p)[5] +
									" % </br>");
					// температура
					grid.setHTML(p, 3, 
							"<h2><p align='center'><img src=" +
							"img/t-norm.gif></br>"+
									
							result.get(p)[6] + " °C </h2></br>");
					// осадки
					grid.setHTML(p, 4, 
									"<p align='center'>" +
									"<img src=img/rain-1.gif></br>" + 
									result.get(p)[7] + 
									" мм.</br>");
					// влажность
					grid.setHTML(p, 5, "<p align='center'>"+ 
							result.get(p)[8] +
							" % </br>");
					// давление
					grid.setHTML(p, 6, 
							"<p align='center'><img src=img/pressure-normal.gif></br>"+
							result.get(p)[9] +
							"</br>мм рт.ст.</br>");
				} else grid.setHTML(p, 1, "нет данных");
			} catch (Exception e) {
				
			}
		}
	}

	/**
	 * Возвращает код HTML для ячейки в таблицу
	 * @param result коллекция с данными
	 * @param row обрабатываемая колонка из коллекции
	 * @return код HTML
	 */
	private String cellText(List<String[]> result, int row) {
		return
			"<p align='center'>"  +
			"<img src=img/"   + result.get(row)[10]+ ">" + // облачность
			""   + result.get(row)[4] + " % </br>" +
			"<h2><p align='center'><img src=img/" + 
			result.get(row)[11]+ ">" + 				// температура
			result.get(row)[5] + " °C </h2></br>" + // в градусах
			"<p align='center'><img src=img/" +
			result.get(row)[12]+ ">" +				//осадки
			result.get(row)[6] + " мм.</br>" +
			"влажность "	+ 
			result.get(row)[7] + " % </br>" +
			"ветер "		+ 
			result.get(row)[14]+ "; " + 
			result.get(row)[9] + " м/с</br>" +
			"<p align='center'><img src=img/" +
			result.get(row)[13]+ ">" + 				//давление
			"<p align='center'>"	 +
			result.get(row)[8] + 
			"</br>мм рт.ст.</br></p>";
	}
}